package com.cmc.cloud.cmclink.doc.service.impl.manifest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cmc.cloud.cmclink.doc.api.document.emums.*;
import com.cmc.cloud.cmclink.doc.api.document.rep.VgmRespDto;
import com.cmc.cloud.cmclink.doc.api.document.rep.manifestrep.manifest.*;
import com.cmc.cloud.cmclink.doc.api.document.rep.manifestrep.manifestcargo.ManifestCargoUpdateReqVO;
import com.cmc.cloud.cmclink.doc.api.document.rep.manifestrep.manifestcntr.ManifestCntrBaseVO;
import com.cmc.cloud.cmclink.doc.api.document.rep.manifestrep.manifestcntr.ManifestCntrLbsUpdateReqVO;
import com.cmc.cloud.cmclink.doc.api.document.rep.manifestrep.manifestcntr.ManifestCntrUpdateReqVO;
import com.cmc.cloud.cmclink.doc.api.document.rep.manifestrep.manifestscn.ManifestScnUpdateReqVO;
import com.cmc.cloud.cmclink.doc.api.document.req.SoManifestReqDto;
import com.cmc.cloud.cmclink.doc.convert.ManifestConvert;
import com.cmc.cloud.cmclink.doc.entity.*;
import com.cmc.cloud.cmclink.doc.mapper.*;
import com.cmc.cloud.cmclink.doc.service.PortDescService;
import com.cmc.cloud.cmclink.doc.service.VgmService;
import com.cmc.cloud.cmclink.doc.service.manifest.ManifestForIbsService;
import com.cmc.cloud.cmclink.doc.service.so.SoSplitCombineService;
import com.cmc.cloud.cmclink.doc.vo.manifestvo.manifest.ManifestCancelVO;
import com.cmc.cloud.cmclink.doc.vo.manifestvo.manifest.ManifestSalveReqVO;
import com.cmc.cloud.cmclink.doc.vo.portdesc.PortDescInfoRespVO;
import com.cmc.cloud.cmclink.doc.vo.vgm.VgmCreateReqVO;
import com.cmc.cloud.cmclink.doc.vo.vgm.VgmQueryInfoVO;
import com.cmes.framework.common.pojo.PageResult;
import com.cmes.framework.mybatis.core.query.LambdaQueryWrapperX;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.cmc.cloud.cmclink.doc.constants.errorconstant.ManifestErrorCodeConstants.*;
import static com.cmes.framework.common.exception.util.ServiceExceptionUtil.exception;


/**
 * 舱单 Service 实现类
 *
 * @author wdq
 */
@Service
@Validated
@Slf4j
public class ManifestForIbsServiceImpl implements ManifestForIbsService {

    @Resource
    private SoMapper soMapper;
    @Resource
    private ManifestMapper manifestMapper;
    @Resource
    private ManifestServiceImpl manifestService;
    @Resource
    private SoVslvoyMapper soVslvoyMapper;
    @Resource
    private VgmService vgmService;
    @Resource
    private PortDescService portDescService;
    @Resource
    private ManifestCntrMapper manifestCntrMapper;
    @Resource
    private ManifestScnMapper manifestScnMapper;
    @Resource
    private SoSplitCombineService soSplitCombineService;
    @Resource
    private BlnoMapper blnoMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @Lock4j(name = "manifestUnique", keys = {"'batchCreateMasterFromSo'", "#userId"})
    public Long createOrUpdateMasterAll(ManifestAllLsbCreateReqVO createReqVO, String userId) {
        if (Objects.isNull(createReqVO.getManifestId())) {
            //创建主舱单
            List<Long> ids = manifestService.batchCreateMasterFromSo(Collections.singletonList(createReqVO.getSoId()), null, SoDataSourceEnum.WEB.getValue(), false);
            createReqVO.setManifestId(ids.get(0));
            //更新舱单信息
            List<String> portCodes = new ArrayList<>(4);
            ManifestDO manifestDO = manifestMapper.selectById(createReqVO.getManifestId());
            portCodes.add(manifestDO.getPorCode());
            portCodes.add(manifestDO.getPolCode());
            portCodes.add(manifestDO.getPodCode());
            portCodes.add(manifestDO.getDelCode());
            // 数据填充
            List<PortDescInfoRespVO> portDescDoList = portDescService.getPortDescInfo(portCodes);
            Map<String, String> portDescMap = portDescDoList.stream().collect(Collectors.toMap(PortDescInfoRespVO::getPortCode, PortDescInfoRespVO::getPortDesc, (first, second) -> first));
            manifestDO.setPorDesc(portDescMap.get(manifestDO.getPorCode()));
            manifestDO.setPolDesc(portDescMap.get(manifestDO.getPolCode()));
            manifestDO.setPodDesc(portDescMap.get(manifestDO.getPodCode()));
            manifestDO.setDelDesc(portDescMap.get(manifestDO.getDelCode()));
            manifestMapper.updateById(manifestDO);
        }
        ManifestAllCreateReqVO mainDto = BeanUtil.copyProperties(createReqVO, ManifestAllCreateReqVO.class);
        Long id = this.updateManifestInfo(mainDto, userId,true);
        //创建vgm数据
        this.getVgmCreateReqList(createReqVO);
        return id;
    }

    @Override
    public List<SoManifestReqDto> queryNotCreateSo(String csmCode) {
        //查询订舱单
        LambdaQueryWrapperX<SoDO> queryWrapperX = new LambdaQueryWrapperX<SoDO>();
        queryWrapperX.eqIfPresent(SoDO::getSoStatus, SoStatusEnum.BookingConfirmed.getValue());
        queryWrapperX.eqIfPresent(SoDO::getValidStatus, ValidStatusEnum.DEFAULT_VALID.getValue());
        queryWrapperX.eqIfPresent(SoDO::getBookingParty, csmCode);
        queryWrapperX.orderByDesc(SoDO::getUpdateTime);
        List<SoDO> soDOList = soMapper.selectList(queryWrapperX);
        //去除审批中的订舱号
        List<SoDO> soDoApplyList = soMapper.selectList(new LambdaQueryWrapperX<SoDO>().eq(SoDO::getBookingParty, csmCode)
                .eq(SoDO::getValidStatus, ValidStatusEnum.AMEND.getValue()));
        List<String> applyBookingNos = soDoApplyList.stream().map(SoDO::getBookingNo).distinct().collect(Collectors.toList());
        soDOList = soDOList.stream().filter(a-> !applyBookingNos.contains(a.getBookingNo())).collect(Collectors.toList());
        //查询已建舱单
        List<ManifestDO> manifestDos = manifestService.findMasterByBookingNos(soDOList.stream().map(SoDO::getBookingNo).collect(Collectors.toList()));
        List<String> bookings = manifestDos.stream().map(ManifestDO::getBookingNo).collect(Collectors.toList());
        List<SoDO> soDos = soDOList.stream().filter(soDO -> !bookings.contains(soDO.getBookingNo())).collect(Collectors.toList());
        List<String> portCodes = new ArrayList<>(16);
        soDos.forEach(e -> {
            portCodes.add(e.getPorCode());
            portCodes.add(e.getPolCode());
            portCodes.add(e.getPodCode());
            portCodes.add(e.getDelCode());
        });
        // 数据填充
        List<PortDescInfoRespVO> portDescDoList = portDescService.getPortDescInfo(portCodes);
        Map<String, String> portDescMap = portDescDoList.stream().collect(Collectors.toMap(PortDescInfoRespVO::getPortCode, PortDescInfoRespVO::getPortDesc, (first, second) -> first));
        List<Long> falseIds = new ArrayList<>();
        soDos.forEach(soDO -> {
            if (Objects.isNull(portDescMap.get(soDO.getPorCode())) || Objects.isNull(portDescMap.get(soDO.getPolCode()))
                    || Objects.isNull(portDescMap.get(soDO.getPodCode())) || Objects.isNull(portDescMap.get(soDO.getDelCode()))) {
                falseIds.add(soDO.getId());
            }
        });
        List<SoManifestReqDto> rtnList = BeanUtil.copyToList(soDos, SoManifestReqDto.class);
        rtnList.forEach(soManifestReqDto -> {
            soManifestReqDto.setPortNameFlag(!falseIds.contains(soManifestReqDto.getId()));
        });
        return rtnList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createOrUpdateSlaveAll(ManifestAllLsbCreateReqVO createReqVO, String userId) {
        Long slaveId = null;
        if (Objects.isNull(createReqVO.getManifestMasterId()) || StringUtil.isBlank(createReqVO.getManifestNoNum())) {
            //主舱单
            throw exception(MANIFEST_MASTER_ID_NOT_EXIST);
        }
        if (Objects.isNull(createReqVO.getManifestId())) {
            // 创建次舱单
            ManifestSalveReqVO salveReq = new ManifestSalveReqVO();
            salveReq.setId(createReqVO.getManifestMasterId());
            salveReq.setManifestNoNum(createReqVO.getManifestNoNum());
            slaveId = manifestService.createSlaveManifest(salveReq, userId, SoDataSourceEnum.WEB.getValue());
            // 次舱单创建完成后还需要通过updateManifestInfo进行更新
            createReqVO.setManifestId(slaveId);
        }
        //更新舱单信息
        ManifestAllCreateReqVO mainDto = BeanUtil.copyProperties(createReqVO, ManifestAllCreateReqVO.class);
        this.updateManifestInfo(mainDto, userId,false);
        //创建vgm
        this.getVgmCreateReqList(createReqVO);
        return slaveId;
    }

    @Override
    public List<ManifestInfoLbsRespVO> getDetailByBookNo(@Valid ManifestQueryReqVO createReqVO) {
        List<ManifestInfoLbsRespVO> rtnList = new ArrayList<>();
        //查询soId
        SoDO soDO = this.querySo(createReqVO.getBookingNo());
        //根据订舱号获取舱单id列表
        List<ManifestDO> manifestDos = manifestMapper.selectList(new LambdaQueryWrapperX<ManifestDO>().eq(ManifestDO::getBookingNo, createReqVO.getBookingNo()));
        if(CollectionUtil.isEmpty(manifestDos)) {
            return rtnList;
        }
        manifestDos = manifestDos.stream().sorted(Comparator.comparing(ManifestDO::getCreateTime)).collect(Collectors.toList());
        //查询舱单详情
        manifestDos.forEach((manifestDO) -> rtnList.add(BeanUtil.copyProperties(manifestService.getManifest(manifestDO.getId()), ManifestInfoLbsRespVO.class)));
        log.info("manifestDos:{}", JSON.toJSONString(manifestDos));
        log.info("rtnList:{}", JSON.toJSONString(rtnList));
        log.info("soDO:{}", JSON.toJSONString(soDO));
        rtnList.forEach(a -> a.getManifest().setSoId(soDO.getId()));
        // 查询vgm
        try {
            AtomicReference<List<VgmRespDto>> vgmList = new AtomicReference<>(new ArrayList<>());
            rtnList.forEach(vo -> {
                if (StringUtil.isBlank(vo.getManifest().getMasterMfNo())) {
                    VgmQueryInfoVO dto = new VgmQueryInfoVO();
                    dto.setCntrNo(vo.getManifestCntrList().stream().map(ManifestCntrLbsUpdateReqVO::getCntrNo).collect(Collectors.toList()));
                    dto.setVesselCode(soDO.getBookingVessel());
                    dto.setVoyage(soDO.getBookingVoyage());
                    List<VgmDO> vgmInfo = vgmService.getVgmInfo(dto);
                    vgmInfo = vgmInfo.stream().filter(e -> Objects.equals(SoDataSourceEnum.WEB.getValue(), e.getDataSource())).collect(Collectors.toList());
                    vgmList.set(BeanUtil.copyToList(vgmInfo, VgmRespDto.class));
                }
            });
            if (!vgmList.get().isEmpty()) {
                Map<String, VgmRespDto> vgmMap = vgmList.get().stream().collect(Collectors.toMap(VgmRespDto::getCntrNo, vgmRespDto -> vgmRespDto));
                rtnList.forEach(vo -> vo.getManifestCntrList().forEach(cntr -> {
                    if (Objects.nonNull(vgmMap.get(cntr.getCntrNo()))) {
                        VgmRespDto vgmRespDto = vgmMap.get(cntr.getCntrNo());
                        cntr.setVgmAddress(vgmRespDto.getAddress());
                        cntr.setVgmSignature(vgmRespDto.getSignature());
                        cntr.setVgmTime(DateUtil.format(vgmRespDto.getTime(), DatePattern.NORM_DATETIME_MINUTE_PATTERN));
                        cntr.setVgmWeight(vgmRespDto.getWeight());
                        cntr.setVgmTypeCode(vgmRespDto.getTypeCode());
                    }
                }));
            }
        } catch (Exception e) {
            log.error("查询vgm错误", e);
        }
        return rtnList;
    }

    @Override
    public PageResult<ManifestIbsRespVO> getManifestPage(@Valid ManifestPageReqVO req) {
        LambdaQueryWrapperX<ManifestDO> lqw = new LambdaQueryWrapperX<>();
        if (StringUtil.isNotBlank(req.getBookingNo())) {
            lqw.like(ManifestDO::getBookingNo, req.getBookingNo());
        }
        if (StringUtil.isNotBlank(req.getReferenceNo())) {
            List<SoDO> soDos = soMapper.selectList(SoDO::getReferenceNo, req.getReferenceNo());
            if (CollectionUtil.isEmpty(soDos)) {
                return new PageResult<>();
            }
            lqw.inIfPresent(ManifestDO::getBookingNo, soDos.stream().map(SoDO::getBookingNo).collect(Collectors.toList()));
        }
        IPage<ManifestDO> page = Page.of(req.getPageNo(), req.getPageSize());
        lqw.eqIfPresent(ManifestDO::getBookingParty, req.getBookingParty());
        //创建人
        lqw.eqIfPresent(ManifestDO::getCreator, req.getCreator());
        lqw.eqIfPresent(ManifestDO::getConfirmStatus, req.getConfirmStatus());
        lqw.likeIfPresent(ManifestDO::getBookingVessel, req.getBookingVessel());
        lqw.likeIfPresent(ManifestDO::getBookingVoyage, req.getBookingVoyage());
        lqw.likeIfPresent(ManifestDO::getPorCode, req.getPorCode());
        lqw.likeIfPresent(ManifestDO::getPolCode, req.getPolCode());
        lqw.likeIfPresent(ManifestDO::getPodCode, req.getPodCode());
        lqw.likeIfPresent(ManifestDO::getDelCode, req.getDelCode());
        lqw.isNull(ManifestDO::getMasterMfNo);
        lqw.orderByDesc(ManifestDO::getUpdateTime);
        IPage<ManifestDO> masterList = manifestMapper.selectPage(page, lqw);
        if (masterList.getRecords().isEmpty()) {
            return new PageResult<>();
        }
        List<ManifestRespVO> respList = ManifestConvert.INSTANCE.convertList(masterList.getRecords());
        //查询次舱单数据
        List<ManifestDO> slaveList = manifestMapper.selectList(new LambdaQueryWrapperX<ManifestDO>()
                .in(ManifestDO::getMasterMfNo, respList.stream().map(ManifestRespVO::getManifestNo).collect(Collectors.toList())));
        respList.addAll(ManifestConvert.INSTANCE.convertList(slaveList));
        manifestService.addSumInfo(respList);
        //查询航线信息
        LambdaQueryWrapperX<SoDO> queryWrapperX = new LambdaQueryWrapperX<SoDO>();
        queryWrapperX.eq(SoDO::getValidStatus,ValidStatusEnum.DEFAULT_VALID.getValue());
        queryWrapperX.in(SoDO::getBookingNo, masterList.getRecords().stream().map(ManifestDO::getBookingNo).collect(Collectors.toList()));
        List<SoDO> soDOList = soMapper.selectList(queryWrapperX);
        // 重复时使用新值（覆盖）
        Map<String, Long> soIdBookingNoMap = soDOList.stream().collect(Collectors.toMap(
                SoDO::getBookingNo,
                SoDO::getId,
                (existing, replacement) -> existing,
                LinkedHashMap::new));
        Map<Long, SoVslvoyDO> soVslvoyDoMap = soVslvoyMapper.seleceFirstLinerBySoIds(soDOList.stream().map(SoDO::getId).collect(Collectors.toList()), TransmodeEnum.LINER.getValue()).stream().collect(Collectors.toMap(SoVslvoyDO::getSoId, e -> e));
        //转换
        List<ManifestIbsRespVO> rtnList = new ArrayList<>();
        List<ManifestRespVO> respMasterList = respList.stream().filter(a -> StringUtil.isBlank(a.getMasterMfNo())).collect(Collectors.toList());
        // 查询提单数据
        List<String> blNos = respMasterList.stream().map(ManifestRespVO::getManifestNo).collect(Collectors.toList());
        List<BlnoDO> blnoList = blnoMapper.selectList(new LambdaQueryWrapperX<BlnoDO>().in(BlnoDO::getBlNo,blNos).eq(BlnoDO::getValid,ValidStatusEnum.DEFAULT_VALID.getValue()));
        // 查询是否可撤销
        List<Long> masterConfirmIds = respMasterList.stream().filter(a->Objects.equals(a.getConfirmStatus(),ConfirmStatusEnum.Y.getValue())).map(ManifestRespVO::getId).collect(Collectors.toList());
        List<String> cancleManifestNoList = new ArrayList<>();
        if(CollectionUtil.isNotEmpty(masterConfirmIds)){
            ManifestCancelVO manifestCancel = manifestService.checkCancel(masterConfirmIds,req.getCreator());
            cancleManifestNoList = manifestCancel.getMainList();
        }
        List<String> finalCancleManifestNoList = cancleManifestNoList;
        respMasterList.forEach(masterDO -> {
            ManifestIbsRespVO rntVO = BeanUtil.copyProperties(masterDO, ManifestIbsRespVO.class);
            rntVO.setManifestCntr(BeanUtil.copyProperties(masterDO, ManifestIbsRespVO.ManifestCntrDesc.class));
            if (Objects.nonNull(soVslvoyDoMap.get(soIdBookingNoMap.get(masterDO.getBookingNo())))) {
                rntVO.setLaneCodeEx(soVslvoyDoMap.get(soIdBookingNoMap.get(masterDO.getBookingNo())).getLaneCodeEx());
            }
            List<ManifestRespVO> respSlaveList = respList.stream().filter(a -> StringUtil.isNotBlank(a.getMasterMfNo()) && Objects.equals(a.getMasterMfNo(), masterDO.getManifestNo())).collect(Collectors.toList());
            rntVO.setSlaveCntrs(BeanUtil.copyToList(respSlaveList, ManifestIbsRespVO.ManifestCntrDesc.class));
            rntVO.setManifestFlag(soSplitCombineService.checkPortAgent(rntVO.getPolCode(),rntVO.getPorCode(),rntVO.getTopAgent()));
            rntVO.setSoId(soIdBookingNoMap.get(masterDO.getBookingNo()));
            rntVO.setBlnoFlag(blnoList.stream().anyMatch(blnoDO -> Objects.equals(blnoDO.getBlNo(),masterDO.getManifestNo())));
            rntVO.setCancelFlag(finalCancleManifestNoList.contains(masterDO.getManifestNo()));
            rtnList.add(rntVO);
        });
        return new PageResult<>(rtnList, masterList.getTotal());
    }

    private Long updateManifestInfo(ManifestAllCreateReqVO createReqVO, String userId,boolean mainFlag) {
        //查询信息
        ManifestDO manifestDO = manifestMapper.selectById(createReqVO.getManifestId());
        if (Objects.isNull(manifestDO)) {
            throw exception(MANIFEST_NOT_EXISTS);
        }
        // 判断装货港是CN的时候，中文品名必输
        createReqVO.getManifestCargoList().forEach(a->{
            if(safeStartsWith(manifestDO.getPolCode(),"CN") && StringUtil.isBlank(a.getCommodityCn())) {
                throw exception(MANIFEST_CHECK_COMMIDITY_CN_ERROR);
            }
        });
        //更新信息
        ManifestUpdateInfoReqVO updateReqVO = new ManifestUpdateInfoReqVO();
        ManifestUpdateReqVO manifestUpdateReqVO = BeanUtil.copyProperties(manifestDO, ManifestUpdateReqVO.class);
        manifestUpdateReqVO.setPayment(createReqVO.getPayment());
        updateReqVO.setManifest(manifestUpdateReqVO);
        updateReqVO.setManifestCntrList(BeanUtil.copyToList(createReqVO.getManifestCntrList(), ManifestCntrUpdateReqVO.class));
        updateReqVO.setManifestCargoList(BeanUtil.copyToList(createReqVO.getManifestCargoList(), ManifestCargoUpdateReqVO.class));
        updateReqVO.setManifestScnList(BeanUtil.copyToList(createReqVO.getManifestScnList(), ManifestScnUpdateReqVO.class));
        List<ManifestCntrDO> updateList = new ArrayList<>();
        if(!mainFlag) {
            // 如果存在拼箱货信息变动，统一更新
            List<ManifestCntrUpdateReqVO> lclList = updateReqVO.getManifestCntrList().stream().filter(a -> Objects.nonNull(a.getLcl())).collect(Collectors.toList());
            if(!lclList.isEmpty()) {
                //查询订舱号对应的所有舱单数据
                List<ManifestDO> updateLclManifest = manifestMapper.selectList(new LambdaQueryWrapperX<ManifestDO>().eq(ManifestDO::getBookingNo, manifestDO.getBookingNo()));
                Map<String, Boolean> lclMap = lclList.stream().collect(Collectors.toMap(ManifestCntrBaseVO::getCntrNo, ManifestCntrBaseVO::getLcl));
                List<Long> lclManifestId = updateLclManifest.stream().map(ManifestDO::getId).collect(Collectors.toList());
                List<ManifestCntrDO> cntrList = manifestCntrMapper.selectList(new LambdaQueryWrapperX<ManifestCntrDO>().in(ManifestCntrDO::getManifestId, lclManifestId));
                cntrList.forEach(a -> {
                    if (Objects.nonNull(lclMap.get(a.getCntrNo()))) {
                        ManifestCntrDO cntrDo = new ManifestCntrDO();
                        cntrDo.setId(a.getId());
                        cntrDo.setManifestId(a.getManifestId());
                        cntrDo.setLcl(lclMap.get(a.getCntrNo()));
                        updateList.add(cntrDo);
                    }
                });
            }
        }
        if (createReqVO.getCommitFlag()) {
            //拼箱货必须有2个分单,存在收货人必须一致
            List<ManifestDO> manifestList = manifestMapper.selectList(new LambdaQueryWrapperX<ManifestDO>().eq(ManifestDO::getBookingNo, manifestDO.getBookingNo()));
            List<Long> manifestIds = manifestList.stream().map(ManifestDO::getId).collect(Collectors.toList());
            List<ManifestCntrDO> cntrList = manifestCntrMapper.selectList(new LambdaQueryWrapperX<ManifestCntrDO>().in(ManifestCntrDO::getManifestId, manifestIds));
            List<ManifestScnDO> scnList = manifestScnMapper.selectList(new LambdaQueryWrapperX<ManifestScnDO>().in(ManifestScnDO::getManifestId, manifestIds));
            List<ManifestCntrDO> lclList = cntrList.stream().filter(a -> Objects.nonNull(a.getLcl()) && a.getLcl()).collect(Collectors.toList());
            lclList.forEach(a -> {
                List<Long> lclManifestIds = lclList.stream().filter(b->Objects.equals(b.getCntrNo(),a.getCntrNo())).map(ManifestCntrDO::getManifestId).collect(Collectors.toList());
                if(lclManifestIds.size() < 3) {
                    throw exception(MANIFEST_CHECK_CLC_SIZE_ERROR);
                }
                List<ManifestScnDO> lclScnList = scnList.stream().filter(b->Objects.equals(b.getPartyTypeCode(), PartyTypeCodeEnum.CONSIGNEE.getValue()) && lclManifestIds.contains(b.getManifestId())).collect(Collectors.toList());
                long allSameCount = lclScnList.stream()
                        .map(ManifestScnDO::getUniqueIdentifierFix)
                        .distinct()
                        .count();
                if(allSameCount>1) {
                    throw exception(MANIFEST_CHECK_CLC_CONSIGNEE_ERROR);
                }
            });
            manifestService.updateManifestAndConfirm(updateReqVO, userId);
        } else {
            manifestService.updateManifest(updateReqVO, userId);
        }
        if (CollectionUtils.isNotEmpty(updateList)) {
            manifestCntrMapper.updateBatch(updateList);
        }
        return manifestDO.getId();
    }

    /**
     * 创建vgm数据
     *
     * @param dto
     * @return
     */
    private void getVgmCreateReqList(ManifestAllLsbCreateReqVO dto) {
        //查询so数据
        SoDO soDO = soMapper.selectById(dto.getSoId());
        List<VgmCreateReqVO> vgmList = new ArrayList<>();
        dto.getManifestCntrList().forEach((cntrVo) -> {
            if (Objects.nonNull(cntrVo.getVgmWeight())) {
                VgmCreateReqVO vgmDto = new VgmCreateReqVO();
                vgmDto.setCurrentPort(soDO.getCurrentPort());
                vgmDto.setVoyage(soDO.getBookingVoyage());
                vgmDto.setVesselCode(soDO.getBookingVessel());
                vgmDto.setCntrNo(cntrVo.getCntrNo());
                vgmDto.setCreator(dto.getCreator());
                vgmDto.setBlNo(soDO.getBlNo());
                vgmDto.setDataSource(SoDataSourceEnum.WEB.getValue());
                vgmDto.setSignature(cntrVo.getVgmSignature());
                vgmDto.setUpdater(dto.getCreator());
                vgmDto.setWeight(cntrVo.getVgmWeight());
                vgmDto.setTypeCode(cntrVo.getVgmTypeCode());
                vgmDto.setAddress(cntrVo.getVgmAddress());
                vgmDto.setTime(cntrVo.getVgmTime());
                vgmList.add(vgmDto);
            }
        });
        if (CollectionUtil.isNotEmpty(vgmList)) {
            vgmService.saveOrupdateVgmInfo(vgmList);
        }
    }

    /**
     * 查询有效so
     * @param bookingNo
     * @return
     */
    private SoDO querySo(String bookingNo){
        //查询soId
        return soMapper.selectOne(new LambdaQueryWrapperX<SoDO>().eq(SoDO::getBookingNo, bookingNo)
                .eq(SoDO::getValidStatus, ValidStatusEnum.DEFAULT_VALID.getValue()));
    }

    /**
     * 判断字符串开头字符
     * @param str
     * @param prefix
     * @return
     */
    public static boolean safeStartsWith(String str, String prefix) {
        return str != null && prefix != null && str.startsWith(prefix);
    }
}
